package features.advance.leetcode.string.easy;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author LIN
 * @date 2022-01-07 15:51
 *
 * 205. 同构字符串
 * // TODO 解析字符串的结构
 *
 * 难度：简单
 *
 * 给定两个字符串 s 和 t，判断它们是否是同构的。
 *
 * 如果 s 中的字符可以按某种映射关系替换得到 t ，那么这两个字符串是同构的。
 *
 * 每个出现的字符都应当映射到另一个字符，同时不改变字符的顺序。不同字符不能映射到同一个字符上，相同字符只能映射到同一个字符上，字符可以映射到自己本身。
 *
 *
 *
 * 示例 1:
 *
 * 输入：s = "egg", t = "add"
 * 输出：true
 * 示例 2：
 *
 * 输入：s = "foo", t = "bar"
 * 输出：false
 * 示例 3：
 *
 * 输入：s = "paper", t = "title"
 * 输出：true
 *
 *
 * 提示：
 *
 * 可以假设 s 和 t 长度相同。
 */
public class Solution205 {

    public static void main(String[] args) {
        Solution v1 = new Solution(){
            @Override
            public boolean isIsomorphic(String s, String t) {
                Map<Character, Character> s2t = new HashMap<Character, Character>(16);
                Map<Character, Character> t2s = new HashMap<Character, Character>(16);
                int len = s.length();
                for (int i = 0; i < len; ++i) {
                    char x = s.charAt(i), y = t.charAt(i);
                    if ((s2t.containsKey(x) && s2t.get(x) != y) || (t2s.containsKey(y) && t2s.get(y) != x)) {
                        return false;
                    }
                    s2t.put(x, y);
                    t2s.put(y, x);
                }
                return true;
            }
        };
        Version version1 = new Version(v1, 1);

        Solution v2 = new Solution(){
            @Override
            public boolean isIsomorphic(String s, String t) {
                char[] map = new char[128], ss = s.toCharArray(), ts = t.toCharArray();
                int n = ss.length;
                boolean[] check = new boolean[128];
                for (int i = 0; i < n; i++) {
                    char a = ss[i], b = ts[i];
                    if (map[a] == 0) {
                        if (check[b]) {
                            return false;
                        }
                        map[a] = b;
                        check[b] = true;
                    } else if (map[a] != b) {
                        return false;
                    }
                }
                return true;
            }
        };
        Version version2 = new Version(v2, 2);

        Solution v3 = new Solution() {
        };
        String[][] test = {
                {"egg","add"},
                {"foo","bar"},
                {"paper","title"},
                {"badc","baba"},
                {"badc","bajh"}
        };
        for (String[] arr : test) {
            String s = arr[0];
            String t = arr[1];
            boolean isomorphic = v1.isIsomorphic(s, t);
            System.out.println("Inputs:"+ Arrays.toString(arr)+"  Outputs:"+isomorphic);
        }

    }

    static class Solution {
        public boolean isIsomorphic(String s, String t) {
            char[] sArray = s.toCharArray();
            char[] tArray = t.toCharArray();
            Map<Character,Character> tmp = new HashMap<>(16);
            for (int i = 0; i < sArray.length; i++) {
                char a = sArray[i];
                char b = tArray[i];
                if(tmp.containsKey(a)){
                    Character c = tmp.get(a);
                    if(c != b){
                        return false;
                    }
                }else{
                    tmp.put(a,b);
                }

            }
            tmp.clear();
            for (int i = 0; i < tArray.length; i++) {
                char a = tArray[i];
                char b = sArray[i];
                if(tmp.containsKey(a)){
                    Character c = tmp.get(a);
                    if(c != b){
                        return false;
                    }
                }else{
                    tmp.put(a,b);
                }

            }
            return true;
        }
    }

    static class Version{
        Solution solution;
        int version;

        public Solution getSolution() {
            return solution;
        }

        public void setSolution(Solution solution) {
            this.solution = solution;
        }

        public int getVersion() {
            return version;
        }

        public void setVersion(int version) {
            this.version = version;
        }

        public Version(Solution solution, int version) {
            this.solution = solution;
            this.version = version;
        }

    }
}
